﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;
using System.Data;
using umbraco.uicontrols;


namespace Our.Umbraco.uDbCompare
{
    public partial class index : System.Web.UI.Page
    {
        private int nodeId
        {
            get
            {
                int nodeId = -1;
                string id = Request.QueryString["id"];
                if (!string.IsNullOrEmpty(id))
                    Int32.TryParse(id, out nodeId);
                return nodeId;
            }
        }

        private string currentConnectionString
        {
            get { return System.Configuration.ConfigurationSettings.AppSettings["umbracoDbDSN"]; }
        }

        private string remoteConnectionString
        {
            get 
            {
                string conn = Session["remoteConnectionString"] as string;
                return conn;
            
            }
            set { Session["remoteConnectionString"] = value; }
        }

        private string username
        {
            get
            {
                string session = string.Format("dbcompare_username_{0}", nodeId);
                string conn = Session[session] as string;
                return conn;

            }
            set 
            {
                string session = string.Format("dbcompare_username_{0}", nodeId);
                Session[session] = value; 
            }
        }

        private string password
        {
            get
            {
                string session = string.Format("dbcompare_password_{0}", nodeId);
                string conn = Session[session] as string;
                return conn;

            }
            set 
            {
                string session = string.Format("dbcompare_password_{0}", nodeId);
                Session[session] = value; 
            }
        }

        private string compareOption
        {
            get
            {
                string option = Session["compareOption"] as string;
                return option;

            }
            set
            {
                Session["compareOption"] = value;
            }
        }


        private string compareLevel
        {
            get
            {
                string level = Session["compareLevel"] as string;
                return level;

            }
            set
            {
                Session["compareLevel"] = value;
            }
        }


        private DbCompareOptions CurrentOption
        {
            get { return (DbCompareOptions)Enum.Parse(typeof(DbCompareOptions), CompareOptionsDropDownList.SelectedValue); }
        }

        private DbCompareLevel CurrentLevel
        {
            get { return (DbCompareLevel)Enum.Parse(typeof(DbCompareLevel), CompareLevelDropDownList.SelectedValue); }
        }

        public TabPage compareTab;
        public TabPage settingsTab;
        public ImageButton saveButtonData;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            compareTab = TabViewDetails.NewTabPage("Compare");
            compareTab.Controls.Add(MainPanel);

            settingsTab = TabViewDetails.NewTabPage("Settings");
            settingsTab.Controls.Add(SettingsPanel);


            //Create a save button for the details tab.
            SetSaveButtonProperties("ImgBtnSaveDetails");

            CacheButton.Click += new EventHandler(CacheButton_Click);
        }

        protected void CacheButton_Click(object sender, EventArgs e)
        {
            username = UsernameTextBox.Text;
            password = PasswordTextBox.Text;

            SetConnectionString();
            BindData();
        }

        private void SetConnectionString()
        {
            string connectionstring = ConnectionStringTextBox.Text;
            if (connectionstring.Contains("{0}") && connectionstring.Contains("{1}") && !string.IsNullOrEmpty(UsernameTextBox.Text))
                remoteConnectionString = string.Format(connectionstring, UsernameTextBox.Text, PasswordTextBox.Text);
            else if (connectionstring.Contains("{0}") && !string.IsNullOrEmpty(UsernameTextBox.Text))
                remoteConnectionString = string.Format(connectionstring, UsernameTextBox.Text);
            else
                remoteConnectionString = connectionstring;

        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                BindData();
        }


        /// <summary>
        /// Set the properites of the savebutton for a tab.
        /// </summary>
        /// <param name="saveButton"></param>
        /// <param name="id"></param>
        private void SetSaveButtonProperties(string id)
        {
            //Create a save button from the current datatab.
            saveButtonData = settingsTab.Menu.NewImageButton();
            saveButtonData.ID = id;
            saveButtonData.Click += new ImageClickEventHandler(SaveButton_Click);
            saveButtonData.AlternateText = "Save";
            saveButtonData.ImageUrl = "~/umbraco/images/editor/save.gif";
        }

        protected void SaveButton_Click(object sender, EventArgs e)
        {
            // Save connection string here
            uDbCompareCMSNode.SaveConnectionName(nodeId, ConnectionNameTextBox.Text);
            uDbCompareCMSNode.SaveConnectionString(nodeId, ConnectionStringTextBox.Text);
        }


        protected void BindData()
        {
            CompareOptionsDropDownList.DataSource = Enum.GetNames(typeof(DbCompareOptions));
            CompareOptionsDropDownList.DataBind();
            if (!string.IsNullOrEmpty(compareOption))
                CompareOptionsDropDownList.SelectedValue = compareOption;

            CompareLevelDropDownList.DataSource = Enum.GetNames(typeof(DbCompareLevel));
            CompareLevelDropDownList.DataBind();
            if (!string.IsNullOrEmpty(compareLevel))
                CompareLevelDropDownList.SelectedValue = compareLevel;

            ResultsPanel.Visible = false;

            UsernameTextBox.Text = username;
            PasswordTextBox.Text = password;
            
            if (nodeId >= 0)
            {
                ConnectionNameTextBox.Text = uDbCompareCMSNode.GetConnectionName(nodeId);
                ConnectionStringTextBox.Text = uDbCompareCMSNode.GetConnectionString(nodeId);
                SetConnectionString();
            }
            ServerLabel.Text = uDbCompare.GetServerName(remoteConnectionString, "unknown");
            if (remoteConnectionString.Contains("{"))
            {
                CompareButton.Enabled = false;
                CompareButton.Text = "Account details need caching";
            }
            else
            {
                CompareButton.Enabled = true;
                CompareButton.Text = "Compare";
            }

            // If we're allowed to compare and there are session variables for CompareOption & CompareLevel
            // then go ahead and compare
            // This could lead to a unintended comparison if you have multiple servers and set the option for one
            // but doesn't really matter much...
            if (CompareButton.Enabled && !string.IsNullOrEmpty(compareOption) && !string.IsNullOrEmpty(compareLevel))
            {
                PopulateAllGrids();
            }
        }

        private void PopulateAllGrids()
        {
            ResultsPanel.Visible = true;

            PopulateGridView(DocTypeTemplateGridView, DbCompareItem.DocTypeTemplate);
            PopulateGridView(DocTypeStructureGridView, DbCompareItem.DocTypeStructure);
            PopulateGridView(DocTypePropertyGridView, DbCompareItem.DocTypeProperty);
            PopulateGridView(MediaTypeStructureGridView, DbCompareItem.MediaTypeStructure);
            PopulateGridView(MediaTypePropertyGridView, DbCompareItem.MediaTypeProperty);
            PopulateGridView(DictionaryGridView, DbCompareItem.Dictionary);
            PopulateGridView(MacroGridView, DbCompareItem.Macro);
            PopulateGridView(RelationTypeGridView, DbCompareItem.RelationType);
            PopulateGridView(TemplateGridView, DbCompareItem.Template);
            PopulateGridView(DataTypeGridView, DbCompareItem.DataType);
        }

        protected void CompareButton_Click(object sender, EventArgs e)
        {
            PopulateAllGrids();

            compareLevel = CompareLevelDropDownList.SelectedValue;
            compareOption = CompareOptionsDropDownList.SelectedValue;
        }

        private void PopulateGridView(GridView gridView, DbCompareItem compareItem)
        {
            DataTable dt = uDbCompare.Compare(compareItem, CurrentOption, CurrentLevel, currentConnectionString, remoteConnectionString);
            if (gridView.Columns.Count == 0)
            {
                HyperLinkField link = new HyperLinkField();
                link.DataTextField = uDbCompare.fieldName;
                link.DataNavigateUrlFields = new string[] {uDbCompare.fieldName};
                link.DataNavigateUrlFormatString = "detail.aspx?CompareItem=" + compareItem + "&name={0}";
                link.HeaderText = uDbCompare.fieldName;
                gridView.Columns.Add(link);

                gridView.Columns.Add(new TemplateField());
                gridView.Columns[1].HeaderText = uDbCompare.GetServerName(currentConnectionString, uDbCompare.left);
                
                gridView.Columns.Add(new TemplateField());
                gridView.Columns[2].HeaderText = uDbCompare.GetServerName(remoteConnectionString, uDbCompare.right);
            }

            gridView.RowDataBound += new GridViewRowEventHandler(gridView_RowDataBound);
            gridView.DataSource = dt;
            gridView.DataBind();
        }
        /*
        private void PopulateGridView(GridView gridView, string key, string table)
        {
            List<string> currentValues = DbCompare.GetValuesFromTableByTable(currentConnectionString, key, table);
            List<string> remoteValues = DbCompare.GetValuesFromTableByTable(remoteConnectionString, key, table);
            PopulateGridView(gridView, currentValues, remoteValues);
        }

        private const string fieldName = "Name";
        private const string left = "left";
        private const string right = "right";
        private const string deepCompare = "deepCompare";

        private void PopulateGridView(GridView gridView, List<string> currentValues, List<string> remoteValues)
        {

            DataTable dt = new DataTable();
            dt.Columns.Add(fieldName, typeof(string));
            dt.Columns.Add(left, typeof(DbCompareMatch));
            dt.Columns.Add(right, typeof(DbCompareMatch));
            dt.Columns.Add(deepCompare, typeof(bool));

            gridView.Columns.Add(new TemplateField());
            gridView.Columns[0].HeaderText = fieldName;
            gridView.Columns.Add(new TemplateField());
            gridView.Columns[1].HeaderText = left;
            gridView.Columns.Add(new TemplateField());
            gridView.Columns[2].HeaderText = right;

            if (CurrentOption == DbCompareOptions.Full)
            {
                foreach (var alias in currentValues)
                {
                    DataRow dr = dt.NewRow();
                    dr[fieldName] = alias;

                    if (CurrentLevel == DbCompareLevel.Name)
                    {
                        dr[left] = DbCompareMatch.Matching;
                        if (remoteValues.Contains(alias))
                        {
                            dr[right] = DbCompareMatch.Matching;
                        }
                        else
                        {
                            dr[right] = DbCompareMatch.Missing;
                        }
                    }

                    dt.Rows.Add(dr);
                }

                foreach (var alias in remoteValues)
                {
                    if (!currentValues.Contains(alias))
                    {
                        var dr = dt.NewRow();
                        dr[fieldName] = alias;

                        if (CurrentLevel == DbCompareLevel.Name)
                        {
                            dr[left] = DbCompareMatch.Missing;
                            dr[right] = DbCompareMatch.Matching;
                        }

                        dt.Rows.Add(dr);
                    }
                }

            }
            else if (CurrentOption == DbCompareOptions.Left)
            {
                foreach (var alias in currentValues)
                {
                    var dr = dt.NewRow();
                    dr[fieldName] = alias;

                    if (CurrentLevel == DbCompareLevel.Name)
                    {
                        dr[left] = DbCompareMatch.Matching;
                        if (remoteValues.Contains(alias))
                        {
                            dr[right] = DbCompareMatch.Matching;
                        }
                        else
                        {
                            dr[right] = DbCompareMatch.Missing;
                        }
                    }

                    dt.Rows.Add(dr);
                }
            }
            else if (CurrentOption == DbCompareOptions.Right)
            {
                foreach (var alias in remoteValues)
                {
                    var dr = dt.NewRow();
                    dr[fieldName] = alias;

                    if (CurrentLevel == DbCompareLevel.Name)
                    {
                        dr[right] = DbCompareMatch.Matching;
                        if (currentValues.Contains(alias))
                        {
                            dr[left] = DbCompareMatch.Matching;
                        }
                        else
                        {
                            dr[left] = DbCompareMatch.Missing;
                        }
                    }

                    dt.Rows.Add(dr);
                }
            }
            else if (CurrentOption == DbCompareOptions.Difference)
            {
                foreach (var alias in currentValues)
                {
                    if (!remoteValues.Contains(alias))
                    {
                        var dr = dt.NewRow();
                        dr[fieldName] = alias;
                        if (CurrentLevel == DbCompareLevel.Name)
                        {
                            dr[left] = DbCompareMatch.Matching;
                            dr[right] = DbCompareMatch.Missing;
                        }
                        dt.Rows.Add(dr);
                    }
                }

                foreach (var alias in remoteValues)
                {
                    if (!currentValues.Contains(alias))
                    {
                        var dr = dt.NewRow();
                        dr[fieldName] = alias;
                        if (CurrentLevel == DbCompareLevel.Name)
                        {
                            dr[left] = DbCompareMatch.Missing;
                            dr[right] = DbCompareMatch.Matching;
                        }
                        dt.Rows.Add(dr);
                    }
                }

            }
            
            gridView.RowDataBound += new GridViewRowEventHandler(gridView_RowDataBound);
            gridView.DataSource = dt;
            gridView.DataBind();

        }
        */

        protected void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                DataRowView drv = e.Row.DataItem as DataRowView;
                if (drv != null)
                {
                    DbCompareMatch leftMatch = (DbCompareMatch)drv[uDbCompare.left];
                    DbCompareMatch rightMatch = (DbCompareMatch)drv[uDbCompare.right];
                    //e.Row.Cells[0].Text = drv[DbCompare.fieldName].ToString();
                    SetCell(e.Row.Cells[1], leftMatch);
                    SetCell(e.Row.Cells[2], rightMatch);
                }
            }
        }

        private void SetCell(TableCell cell, DbCompareMatch match)
        {
            switch (match)
            {
                case DbCompareMatch.Matching:
                    cell.BackColor = System.Drawing.Color.Green;
                    break;
                case DbCompareMatch.Missing:
                    cell.BackColor = System.Drawing.Color.Red;
                    break;
                case DbCompareMatch.NonMatching:
                    cell.BackColor = System.Drawing.Color.Yellow;
                    break;
            }
        }

    }
}
